package cn.turboinfo.fuyang.api.provider.admin.impl.log;

import cn.turboinfo.fuyang.api.domain.admin.service.log.LoginLogService;
import cn.turboinfo.fuyang.api.entity.admin.exception.log.LoginLogException;
import cn.turboinfo.fuyang.api.entity.admin.pojo.log.LoginLog;
import cn.turboinfo.fuyang.api.entity.admin.pojo.log.LoginLogCreator;
import cn.turboinfo.fuyang.api.provider.admin.repository.database.log.LoginLogDAO;
import cn.turboinfo.fuyang.api.provider.admin.repository.database.log.LoginLogPO;
import lombok.RequiredArgsConstructor;
import net.sunshow.toolkit.core.base.enums.YesNoStatus;
import net.sunshow.toolkit.core.qbean.api.request.QPage;
import net.sunshow.toolkit.core.qbean.api.request.QRequest;
import net.sunshow.toolkit.core.qbean.api.response.QResponse;
import net.sunshow.toolkit.core.qbean.helper.component.request.QBeanCreatorHelper;
import net.sunshow.toolkit.core.qbean.helper.service.impl.AbstractQServiceImpl;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;

@RequiredArgsConstructor
@Service
public class LoginLogServiceImpl extends AbstractQServiceImpl<LoginLog> implements LoginLogService {
    private final LoginLogDAO loginLogDAO;

    @Override
    public Optional<LoginLog> getById(Long id) {
        return loginLogDAO.findById(id).map(this::convertQBean);
    }

    @Override
    public LoginLog getByIdEnsure(Long id) {
        return getById(id).orElseThrow(this.getExceptionSupplier("未找到数据, id=" + id, null));
    }

    @Override
    public List<LoginLog> findByIdCollection(Collection<Long> idCollection) {
        return convertStreamQBeanToList(loginLogDAO.findByIdInOrderByIdDesc(idCollection).stream());
    }

    @Override
    @Transactional
    public LoginLog save(LoginLogCreator creator) throws LoginLogException {
        LoginLogPO loginLogPO = new LoginLogPO();

        QBeanCreatorHelper.copyCreatorField(loginLogPO, creator);

        return convertQBean(loginLogDAO.save(loginLogPO));
    }

    @Override
    @Transactional
    public LoginLog save(String loginSource, String username, Long sysUserId, YesNoStatus loginStatus, String loginRemark) throws LoginLogException {
        LoginLogPO loginLogPO = new LoginLogPO();

        loginLogPO.setLoginSource(loginSource);
        loginLogPO.setUsername(username);
        loginLogPO.setSysUserId(sysUserId);
        loginLogPO.setLoginStatus(loginStatus);
        loginLogPO.setLoginRemark(loginRemark);
        loginLogPO.setLoginTime(LocalDateTime.now());

        return convertQBean(loginLogDAO.save(loginLogPO));
    }

    @Override
    public QResponse<LoginLog> findAll(QRequest request, QPage requestPage) {
        return convertQResponse(findAllInternal(request, requestPage));
    }

    private Page<LoginLogPO> findAllInternal(QRequest request, QPage requestPage) {
        return loginLogDAO.findAll(convertSpecification(request), convertPageable(requestPage));
    }

    @Override
    @Transactional
    public void deleteById(Long id) throws LoginLogException {
        LoginLogPO loginLogPO = getEntityWithNullCheckForUpdate(id, loginLogDAO);
        loginLogPO.setDeletedTime(System.currentTimeMillis());
    }

    @Override
    public List<LoginLog> findLatestNByUsername(String username, int n) {
        return convertStreamQBeanToList(loginLogDAO.findByUsernameOrderByLoginTimeDesc(username, PageRequest.of(0, n)).stream());
    }

    @Override
    protected Supplier<? extends RuntimeException> getExceptionSupplier(String message,
                                                                        Throwable cause) {
        return () -> new LoginLogException(message, cause);
    }
}
